package com.example.demo.service;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.AbstractMap.SimpleEntry;
import java.util.HashMap;

import it.unisa.dia.gas.jpbc.Element;
import it.unisa.dia.gas.plaf.jpbc.field.curve.CurveElement;
import it.unisa.dia.gas.plaf.jpbc.field.z.ZrElement;

public class Fabric {
	public  PubParams p;

   public List<Element> mu;
    private Map<Element,Element> skMap;
    private ZrElement MSK;
    ProxyReEncrypt  d=new ProxyReEncrypt ();
    private Element A;
    public List<Element> getIDs(){
    	return mu;
    }
    
//    public void saveIDToFile(List<Element> ids) throws IOException, ClassNotFoundException {
//    	List<byte[]> idbytes=new LinkedList<>();
//    	for(Element id:ids) {
//    		idbytes.add(id.toBytes());
//    	}
//    	String path="data/ids";
//    	FileOutputStream fwriter = new FileOutputStream(path);
//    	ObjectOutputStream objectOutputStream = new ObjectOutputStream(fwriter);
//    	objectOutputStream.writeObject(idbytes);
//    	
//    }
    
	public Fabric(PubParams p,int m,int t,Element MSK) {
		// TODO Auto-generated constructor stub
		
		this.p=p;
		this.skMap=new HashMap<>();

		this.MSK = (ZrElement) MSK;
		mu=new LinkedList<>();
	}
	public LinkedList<String> KeyGen() {
		   
		   Element ID_i=p.Zr.newRandomElement();
		   mu.add(ID_i);
		   SimpleEntry<Element,Element> ski=d.KeyGen(p,MSK,ID_i);
		   
		   skMap.put(ID_i, ski.getValue());
		   
		   LinkedList<String> ls=new LinkedList<>();
		   try {
			ls.add( new String(ID_i.toBytes(), "ISO-8859-1"));
			ls.add(new String(ski.getKey().toBytes(), "ISO-8859-1"));
			 ls.add(new String(ski.getValue().toBytes(), "ISO-8859-1"));
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		   
		   return ls;
	}
	public List<Element> aggregate(List<Element> mu1){
		List<Element> P=new LinkedList<Element>();
		ZrElement A1=MSK.duplicate().add(p.hash(mu1.get(0).duplicate()));
		P.add(p.h.duplicate().mulZn(A1));
		for(int i=1;i<mu1.size();i++) {
			A1=A1.duplicate().mul(MSK.duplicate().add(p.hash(mu1.get(i).duplicate())));
			P.add(p.h.duplicate().mulZn(A1));
		}
		return P;
	}
	public void setA(List<Element> mu1) {
		ZrElement A=MSK.duplicate().add(p.hash(mu1.get(0).duplicate()));
		for(int i=1;i<mu1.size();i++) {
			A=A.duplicate().mul(MSK.duplicate().add(p.hash(mu1.get(i).duplicate())));
		}
		this.A=A;
		//d.writeFile("data/A", A.toBytes());
		
	}
	public Element getA() {
		return this.A;
	}
	
	public Fabric init() {
		ProxyReEncrypt  d=new ProxyReEncrypt ();
		
		int m=5,t=3;
		SimpleEntry<PubParams,Element> retMap=d.setup();
		PubParams p=retMap.getKey();
		d.save(p);
		SystemProperty.writeProperties("m", "5");
		SystemProperty.writeProperties("t", "3");
		Fabric f=new Fabric(p,m,t,retMap.getValue());
		return f;
	}
}
